﻿using System.Linq;
using System.Web.Mvc;

namespace UserStories.Controllers
{
    using System.Collections.Generic;

    using UserStories.Attributes;
    using UserStories.Models;
    using UserStories.ViewModels.Projects;

    [Authorize]
    [User]
    public class ProjectsController : Controller
    {
        private readonly IProjectsService _projectsService;

        public User User
        {
            get
            {
                return ViewBag.User as User;
            }
        }

        public ProjectsController()
            : this(FakeProjectsService.Instance())
        {

        }

        public ProjectsController(IProjectsService projectsService)
        {
            _projectsService = projectsService;
        }

        [HttpGet]
        public ActionResult Index()
        {
            // Gets data
            var roles = _projectsService.Roles();
            var projects =
                _projectsService.ProjectsForIndex()
                                .Select(
                                    p =>
                                    new IndexViewModelProject
                                        {
                                            Id = p.Id,
                                            Name = p.Name,
                                            Description = p.Description,
                                            Role =
                                                roles.FirstOrDefault(
                                                    r =>
                                                    r.Id
                                                    == (User.RoleInProject(p) != null
                                                            ? User.RoleInProject(p).Id
                                                            : 0)) != null
                                                    ? roles.FirstOrDefault(
                                                        r =>
                                                        r.Id
                                                        == (User.RoleInProject(p) != null
                                                                ? User.RoleInProject(p).Id
                                                                : 0)).Name
                                                    : "[no role]"
                                        });

            // Creates the view model
            var viewModel = new IndexViewModel { Projects = projects };

            return View(viewModel);
        }

        [HttpGet]
        public ActionResult Edit(int id)
        {
            // Gets the Data
            var project = id != 0 ? _projectsService.ProjectForEdit(id) : new Project();
            var roles = _projectsService.Roles();
            var users = _projectsService.Users();
            var pokerCards = _projectsService.PokerCards();

            // Creates the view model
            var viewModel = new EditViewModel
                                {
                                    Id = project.Id,
                                    Name = project.Name,
                                    Description = project.Description,
                                    Releases = project.NumberOfReleases,
                                    WeeksPerSprint = project.WeeksPerSprint,
                                    Team =
                                        project.Team.Select(
                                            t =>
                                            new EditViewModelUser
                                                {
                                                    Id = t.Id,
                                                    RoleId = t.RoleInProject(project).Id
                                                }),
                                    UserStories = project.UserStories.Select(
                                            u =>
                                            new EditViewModelUserStory
                                                {
                                                    Id = u.Id,
                                                    Description = u.Description,
                                                    Priority = u.Priority,
                                                    CardId = u.Points.Id
                                                }),
                                    Sprints = project.Sprints.Select(s => new EditViewModelSprint
                                                                              {
                                                                                  Id = s.Id,
                                                                                  ReleaseId = s.Release.Id,
                                                                                  EditLink = Url.Action("EditSprint", new { id = s.Id, projectId = project.Id })
                                                                              }),
                                    Roles = roles.Select(r => new IdNamePair { Id = r.Id, Name = r.Name }),
                                    Users = users.Select(u => new IdNamePair { Id = u.Id, Name = u.Name }),
                                    PokerCards = pokerCards.Select(p => new IdNamePair { Id = p.Id, Name = p.Name }),
                                };


            return View(viewModel);
        }

        [HttpPost]
        public ActionResult Edit(EditFormModel edit)
        {
            // Creates model graph
            var project = new Project
                              {
                                  Id = edit.Id,
                                  Name = edit.Name,
                                  Description = edit.Description,
                                  NumberOfReleases = edit.Releases,
                                  WeeksPerSprint = edit.WeeksPerSprint,
                                  UserStories = edit.UserStories != null ?
                                      edit.UserStories.Select(
                                          u =>
                                          new UserStory
                                              {
                                                  Id = u.Id,
                                                  Description = u.Description,
                                                  Priority = u.Priority,
                                                  Points = new PokerCard { Id = u.CardId },
                                                  Project = new Project{Id = edit.Id}
                                              }) : Enumerable.Empty<UserStory>(),
                                  Sprints = edit.Sprints != null?
                                  edit.Sprints.Select(s => new Sprint
                                                                         {
                                                                             Id = s.Id,
                                                                             Release = new Release{Id = s.ReleaseId},
                                                                             Project = new Project{Id = edit.Id}
                                                                         }) : Enumerable.Empty<Sprint>()
                              };

            project.Team = edit.Team != null
                               ? edit.Team.Select(
                                   t =>
                                   new User
                                       {
                                           Id = t.Id,
                                           Roles =
                                               new Dictionary<int, Role>
                                                   {
                                                       { project.Id, new Role { Id = t.RoleId } }
                                                   }
                                       })
                               : Enumerable.Empty<User>();

            // Validates form

            if (User.IsSysAdmin)
            {
                _projectsService.SaveAsSysAdmin(project);
            }
            
            if (User.IsRoleInProject(project.Id, Role.ProductOwner))
            {
                _projectsService.SaveAsProductOwner(project);
            }
            
            if (User.IsRoleInProject(project.Id, Role.ScrumMaster))
            {
                _projectsService.SaveAsScrumMaster(project);
            }

            // TODO set success message
            return RedirectToAction("Index");
        }

        [HttpGet]
        public ActionResult CreateUser(int id)
        {
            var viewModel = new CreateUserViewModel { ProjectId = id };
            return this.View(viewModel);
        }

        [HttpPost]
        public ActionResult CreateUser(CreateUserFormModel userFormModel)
        {
            var user = new User { Name = userFormModel.Name, Email = userFormModel.Email };

            _projectsService.Save(user);

            return RedirectToAction("Edit", new { id = userFormModel.ProjectId });
        }

        [HttpGet]
        public ActionResult EditSprint(int id, int projectId)
        {
            var sprint = _projectsService.Sprint(id);
            IEnumerable<UserStory> userStories = _projectsService.UsersStoriesForProject(projectId);
            var viewModel = new EditSprintViewModel
                                {
                                    Id = sprint.Id,
                                    ProjectId = projectId,
                                    Review = sprint.Review,
                                    UserStories =
                                        sprint.UserStories.Select(
                                            u =>
                                            new EditSprintViewModelUserStory
                                                {
                                                    Id = u.Id,
                                                    Description =
                                                        u.Description
                                                }),
                                    AllUserStories =
                                        userStories.Select(
                                            u =>
                                            new EditSprintViewModelUserStory
                                                {
                                                    Id = u.Id,
                                                    Description =
                                                        u.Description
                                                })
                                };

            return View(viewModel);
        }

        [HttpPost]
        public ActionResult EditSprint(EditSprintFormModel formModel)
        {
            var sprint = new Sprint
                             {
                                 Id = formModel.Id,
                                 Review = formModel.Review,
                                 Project = new Project { Id = formModel.ProjectId },
                                 UserStories =
                                     formModel.UserStories != null
                                         ? formModel.UserStories.Select(u => new UserStory { Id = u.Id })
                                         : Enumerable.Empty<UserStory>()
                             };
            _projectsService.Save(sprint);
            return RedirectToAction("Edit", new { id = formModel.ProjectId });
        }
    }
}
